package com.cheer.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheer.dao.OaIntegralDao;
import com.cheer.dao.OaIntegralDetailDao;
import com.cheer.dto.OaIntegralDTO;
import com.cheer.entity.*;
import com.cheer.enums.OaIntegralRuleEnum;
import com.cheer.exception.ServiceException;
import com.cheer.job.OaLearnListener;
import com.cheer.service.*;
import com.cheer.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service("oaIntegralDetailService")
public class OaIntegralServiceImpl extends ServiceImpl<OaIntegralDao, OaIntegralEntity> implements OaIntegralService {

    @Autowired
    private OaIntegralDao oaIntegralDao;

    @Autowired
    private OaUserService oaUserService;

    @Autowired
    private OaLearnService oaLearnService;

    @Autowired
    private OaArticleService oaArticleService;

    @Autowired
    private OaLearnEntryService oaLearnEntryService;

    @Autowired
    private OaLearnClassService oaLearnClassService;

    @Autowired
    private OaIntegralDetailDao oaIntegralDetailDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private OaRuleService oaRuleService;

    @Override
    public OaCreditVO listByUserId(Integer userId) {
        OaUserEntity user = oaUserService.getById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }
        List<OaIntegralEntity> detailList = oaIntegralDao.selectListByOpenid(user.getOpenid());
        List<OaCreditListVO> infoList = new ArrayList<>();

        for (OaIntegralEntity detail : detailList) {

            OaCreditListVO oaCreditListVO = new OaCreditListVO();
            oaCreditListVO.setCredit(detail.getIntegral())
                    .setTime(DateUtil.format(detail.getAddTime(), DatePattern.NORM_DATETIME_PATTERN));

            if (OaIntegralRuleEnum.LOGIN.getCode().equals(detail.getType())) {
                oaCreditListVO.setName("每日登录");
            } else if (OaIntegralRuleEnum.CURRENT.getCode().equals(detail.getType())
                    || OaIntegralRuleEnum.PAST.getCode().equals(detail.getType())) {
                String learnName = oaLearnService.getFullName(detail.getItemsId());
                oaCreditListVO.setName("观看了" + learnName + "的大学习");
            } else if (OaIntegralRuleEnum.ARTICLE.getCode().equals(detail.getType())) {
                String articleName = oaArticleService.getTitle(detail.getItemsId());
                oaCreditListVO.setName("阅读了" + articleName);
            } else if (OaIntegralRuleEnum.ARTICLE_PIC.getCode().equals(detail.getType())) {
                String articleName = oaArticleService.getTitle(detail.getItemsId());
                oaCreditListVO.setName("阅读了" + articleName);
            }else if (OaIntegralRuleEnum.ARTICLE_WIN.getCode().equals(detail.getType())) {
                String articleName = oaArticleService.getTitle(detail.getItemsId());
                oaCreditListVO.setName("阅读了" + articleName);
            }else if (OaIntegralRuleEnum.VIDEO.getCode().equals(detail.getType())) {
                String videoName = oaArticleService.getTitle(detail.getItemsId());
                oaCreditListVO.setName("观看了" + videoName);
            } else if (OaIntegralRuleEnum.CURR_HUN.getCode().equals(detail.getType())
                    || OaIntegralRuleEnum.PAST_HUN.getCode().equals(detail.getType())) {
                String learnName = oaArticleService.getTitle(detail.getItemsId());
                oaCreditListVO.setName("学习了" + learnName);
            }else if (OaIntegralRuleEnum.MATCH.getCode().equals(detail.getType())) {
                oaCreditListVO.setName(OaIntegralRuleEnum.MATCH.getMessage());
            }else if (OaIntegralRuleEnum.EXCHANGE.getCode().equals(detail.getType())) {
                oaCreditListVO.setName("浏览了" + OaIntegralRuleEnum.EXCHANGE.getMessage());
            }else if (OaIntegralRuleEnum.ACTIVITY.getCode().equals(detail.getType())) {
                oaCreditListVO.setName("浏览了" +OaIntegralRuleEnum.ACTIVITY.getMessage());
            }

            infoList.add(oaCreditListVO);
        }

        return new OaCreditVO()
                .setTotal(user.getIntegral())
                .setCreditList(infoList);
    }

    @Override
    public List<CreditDateVO>  listCredit(Integer pageNum, Integer pageSize, Integer userId) {
        OaUserEntity user = oaUserService.getById(userId);
        if (user == null) {
            return new ArrayList<>();
        }

        int start = (pageNum - 1) * pageSize;
        int offset = pageSize;
        List<OaIntegralEntity> creditRecordList = oaIntegralDao.selectListByOpenidLimit(start, offset, user.getOpenid());

        Map<String, List<CreditRecordVO>> map = new LinkedHashMap<>();
        for (OaIntegralEntity creditRecord : creditRecordList) {
            CreditRecordVO creditVO = new CreditRecordVO()
                    .setTime(DateUtil.format(creditRecord.getAddTime(), DatePattern.NORM_DATETIME_PATTERN));

            if (OaIntegralRuleEnum.LOGIN.getCode().equals(creditRecord.getType())) {
                creditVO.setName("每日登录");
            } else if (OaIntegralRuleEnum.CURRENT.getCode().equals(creditRecord.getType())
                    || OaIntegralRuleEnum.PAST.getCode().equals(creditRecord.getType())) {
                String learnName = oaLearnService.getFullName(creditRecord.getItemsId());
                creditVO.setName("观看了" + learnName + "的大学习");
            } else if (OaIntegralRuleEnum.ARTICLE.getCode().equals(creditRecord.getType())) {
                String articleName = oaArticleService.getTitle(creditRecord.getItemsId());
                creditVO.setName("阅读了" + articleName);
            }else if (OaIntegralRuleEnum.ARTICLE_PIC.getCode().equals(creditRecord.getType())) {
                String articleName = oaArticleService.getTitle(creditRecord.getItemsId());
                creditVO.setName("阅读了" + articleName);
            }else if (OaIntegralRuleEnum.ARTICLE_WIN.getCode().equals(creditRecord.getType())) {
                String articleName = oaArticleService.getTitle(creditRecord.getItemsId());
                creditVO.setName("阅读了" + articleName);
            } else if (OaIntegralRuleEnum.VIDEO.getCode().equals(creditRecord.getType())) {
                String videoName = oaArticleService.getTitle(creditRecord.getItemsId());
                creditVO.setName("观看了" + videoName);
            } else if (OaIntegralRuleEnum.CURR_HUN.getCode().equals(creditRecord.getType())
                    || OaIntegralRuleEnum.PAST_HUN.getCode().equals(creditRecord.getType())) {
                String learnName = oaArticleService.getTitle(creditRecord.getItemsId());
                creditVO.setName("学习了" + learnName);
            }else if (OaIntegralRuleEnum.ARTICLE_PIC.getCode().equals(creditRecord.getType())
                    || OaIntegralRuleEnum.ARTICLE_WIN.getCode().equals(creditRecord.getType())) {
                String learnName = oaArticleService.getTitle(creditRecord.getItemsId());
                creditVO.setName("学习了" + learnName);
            }else if (OaIntegralRuleEnum.MATCH.getCode().equals(creditRecord.getType())) {
                creditVO.setName(OaIntegralRuleEnum.MATCH.getMessage());
            }else if (OaIntegralRuleEnum.EXCHANGE.getCode().equals(creditRecord.getType())) {
                creditVO.setName("浏览了" + OaIntegralRuleEnum.EXCHANGE.getMessage());
            }else if (OaIntegralRuleEnum.ACTIVITY.getCode().equals(creditRecord.getType())) {
                creditVO.setName("浏览了" + OaIntegralRuleEnum.ACTIVITY.getMessage());
            }


            creditVO.setValue("+" + creditRecord.getIntegral() + "积分");
            String date = DateUtil.format(creditRecord.getAddTime(), DatePattern.NORM_DATE_PATTERN);

            if (map.containsKey(date)) {
                map.get(date).add(creditVO);
            } else {
                List<CreditRecordVO> list = new ArrayList<>();
                list.add(creditVO);
                map.put(date, list);
            }
        }

        List<CreditDateVO> result = new ArrayList<>();
        for (Map.Entry<String, List<CreditRecordVO>> entry : map.entrySet()) {
            CreditDateVO creditDateVO = new CreditDateVO();
            creditDateVO.setDate(entry.getKey());
            creditDateVO.setCredit(entry.getValue());
            result.add(creditDateVO);
        }

        return result;
    }

    @Override
    public void add(Integer userId, String openid, OaIntegralRuleEnum integralRuleEnum, Integer itemsId) {
        Date date = new Date();
        Integer type = integralRuleEnum.getCode();
        String typeStr = String.valueOf(integralRuleEnum.getCode());
        Integer integral = integralRuleEnum.getIntegral();
        String currentSecond = String.valueOf(DateUtil.currentSeconds());
        Boolean isExec = false;

        switch (integralRuleEnum) {
            case LOGIN:
                if (oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                        DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) <= 0) {
                    isExec = true;
                }
                break;
            case CURRENT:
                if (oaIntegralDao.selectCountByItemsId(openid, integralRuleEnum.getCode(), itemsId) <= 0) {
                    OaLearnListener.putTask(openid, integralRuleEnum, itemsId);
                }
                break;

            case PAST:
                if ((oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                        DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) < 2) &&
                        (oaIntegralDao.selectCountByOpenidAndItemsId(openid, integralRuleEnum.getCode(), itemsId,
                                DateUtil.beginOfWeek(date), DateUtil.endOfWeek(date)) <= 0)) {
                    OaLearnListener.putTask(openid, integralRuleEnum, itemsId);
                }
                break;
            case ARTICLE:
                isExec = isPass(openid, integralRuleEnum, itemsId, integralRuleEnum.getMax());
                break;
            case ARTICLE_PIC:
                isExec = isPass(openid, integralRuleEnum, itemsId, integralRuleEnum.getMax());
                break;
            case ARTICLE_WIN:
                isExec = isPass(openid, integralRuleEnum, itemsId, integralRuleEnum.getMax());
                break;
            case VIDEO:
                if ((oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                        DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) <= 4) &&
                        (oaIntegralDao.selectCountByOpenidAndItemsId(openid, integralRuleEnum.getCode(), itemsId,
                        DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) <= 0)) {
                    isExec = true;
                }
                break;
            case CURR_HUN:
                if (oaIntegralDao.selectCountByItemsId(openid, integralRuleEnum.getCode(),
                        itemsId) <= 0) {
                    isExec = true;
                }
                break;
            // 积分兑换
            case EXCHANGE:
                if (oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                        DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) <= 0) {
                    isExec = true;
                }
                break;
            // 主题活动
            case ACTIVITY:
                if (oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                        DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) <= 0) {
                    isExec = true;
                }
                break;
            case PAST_HUN:
                if ((oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                        DateUtil.beginOfWeek(date), DateUtil.endOfWeek(date)) <= 9) &&
                        (oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                                DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) <= 1)) {
                    isExec = true;
                }
                break;
            default:
                break;
        }

        // 执行积分的增加
        if(isExec){
            oaIntegralDao.insert(new OaIntegralEntity(type, integral, openid, itemsId));
            OaIntegralDetailEntity insertDetail = new OaIntegralDetailEntity()
                    .setIntegral(integral)
                    .setType(typeStr)
                    .setOpenid(openid)
                    .setStatus(1)
                    .setAddTime(currentSecond);
            oaIntegralDetailDao.insert(insertDetail);
            oaUserService.addCredit(userId, integralRuleEnum.getIntegral());
        }

    }

    private boolean isPass( String openid, OaIntegralRuleEnum integralRuleEnum,
                            Integer itemsId, Integer max ) {

        Boolean compareResult = oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                DateUtil.beginOfDay(new Date()), DateUtil.endOfDay(new Date())) <= (max - 1);

        Boolean toDayIsRead = oaIntegralDao.selectCountByOpenidAndItemsId(openid, integralRuleEnum.getCode(), itemsId,
                DateUtil.beginOfDay(new Date()), DateUtil.endOfDay(new Date())) <= 0;

        return ( compareResult && toDayIsRead );
    }

    @Override
    public void add(String openid, OaIntegralRuleEnum integralRuleEnum, Integer itemsId, Date date) {
        switch (integralRuleEnum) {
            case CURRENT:
                if (oaIntegralDao.selectCountByItemsId(openid, integralRuleEnum.getCode(), itemsId) <= 0) {

                    OaIntegralEntity insertIntegralDetail = new OaIntegralEntity()
                            .setIntegral(integralRuleEnum.getIntegral())
                            .setType(integralRuleEnum.getCode())
                            .setItemsId(itemsId)
                            .setOpenid(openid)
                            .setAddTime(date);
                    oaIntegralDao.insert(insertIntegralDetail);

                    OaIntegralDetailEntity insertDetail = new OaIntegralDetailEntity()
                            .setIntegral(integralRuleEnum.getIntegral())
                            .setType(String.valueOf(integralRuleEnum.getCode()))
                            .setItemsId(String.valueOf(itemsId))
                            .setOpenid(openid)
                            .setStatus(1)
                            .setAddTime(String.valueOf(date.getTime() / 1000));
                    oaIntegralDetailDao.insert(insertDetail);

                    oaUserService.addCredit(oaUserService.getIdByOpenid(openid), integralRuleEnum.getIntegral());
                }

                oaLearnEntryService.add(openid, itemsId, date);

                break;

            case PAST:
                if ((oaIntegralDao.selectCountByOpenid(openid, integralRuleEnum.getCode(),
                        DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) <= 1) &&
                        (oaIntegralDao.selectCountByOpenidAndItemsId(openid, integralRuleEnum.getCode(), itemsId,
                                DateUtil.beginOfDay(date), DateUtil.endOfDay(date)) <= 0)) {

                    OaIntegralEntity insertIntegralDetail = new OaIntegralEntity()
                            .setIntegral(integralRuleEnum.getIntegral())
                            .setType(integralRuleEnum.getCode())
                            .setItemsId(itemsId)
                            .setOpenid(openid)
                            .setAddTime(date);
                    oaIntegralDao.insert(insertIntegralDetail);

                    OaIntegralDetailEntity insertDetail = new OaIntegralDetailEntity()
                            .setIntegral(integralRuleEnum.getIntegral())
                            .setType(String.valueOf(integralRuleEnum.getCode()))
                            .setItemsId(String.valueOf(itemsId))
                            .setOpenid(openid)
                            .setStatus(1)
                            .setAddTime(String.valueOf(date.getTime() / 1000));
                    oaIntegralDetailDao.insert(insertDetail);

                    oaUserService.addCredit(oaUserService.getIdByOpenid(openid), integralRuleEnum.getIntegral());
                }

                break;

            default:
                break;
        }
    }

    @Override
    public Integer getByYear(String openid, Integer userId) {

        Date date = new Date();
        String redisKey = getCreditYearKey(userId, date);
        String creditYear = stringRedisTemplate.boundValueOps(redisKey).get();
        if(StrUtil.isBlank(creditYear)){
            creditYear = String.valueOf(oaIntegralDao.selectSumByOpenid(openid, DateUtil.beginOfYear(date), DateUtil.endOfYear(date)));
            stringRedisTemplate.opsForValue().set( redisKey, creditYear, 30, TimeUnit.DAYS );
        }
        return Integer.valueOf(creditYear);
    }

    /**
     * 获取积分Key
     * @param userId
     * @param date
     * @return
     */
    public String getCreditYearKey(Integer userId, Date date){
        return userId+"_credit_"+DateUtil.format(date, "yyyy");
    }

    @Override
    public void updateYearCatch(Integer userId, Integer addCredit) {
        String redisKey = getCreditYearKey(userId, new Date());
        String creditYear = stringRedisTemplate.boundValueOps(redisKey).get();
        if(StrUtil.isNotBlank(creditYear)){
            Integer creditAddResult =  Integer.valueOf(creditYear) + addCredit;
            stringRedisTemplate.opsForValue().set( redisKey, String.valueOf(creditAddResult), 30, TimeUnit.DAYS );
        }
    }

    @Override
    public UserMainVO getUserMainVo(Integer userId,  String openId) {

        OaUserEntity user = oaUserService.getById(userId);
        OaLevelVO level = oaRuleService.getLevel(userId, openId);
        UserMainVO userMainVO = new UserMainVO();
        // 获取等级URL
        userMainVO.setHonorUrl(level.getIconUrl());
        // 获取等级信息
        userMainVO.setHonorTitle(level.getHonorTitle());
        // 鲜花数量
        userMainVO.setFlowerNum(user.getFlower());

        return userMainVO;
    }

    @Override
    public List<OaIntegralDTO> getRecentIntegral(int limit, String openid) {
        return oaIntegralDao.getRecentIntegral(limit, openid);
    }

    @Override
    public List<AudioVO> getAudio() {
        return oaIntegralDao.getAudio();
    }

    Map<String, Collection<OaLearnClassEntity>> map = new HashMap<>();
    @Override
    public String getAllOrgName(String path) {

        String[] split = path.split(",");
        List<String> collect = Arrays.stream(split).collect(Collectors.toList());
        Collection<OaLearnClassEntity> oaLearnClassEntities = new ArrayList<>();
        if(map.containsKey(path)){
            oaLearnClassEntities = map.get(path);
        }else{
            oaLearnClassEntities = oaLearnClassService.listByIds(collect);
            map.put(path,oaLearnClassEntities);
        }
        return oaLearnClassEntities.stream().map(OaLearnClassEntity::getName).collect(Collectors.joining("-"));
    }

    @Override
    public List<OaIntegralEntity> listByUserId2(Integer userId) {
        OaUserEntity user = oaUserService.getById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }
        List<OaIntegralEntity> detailList = oaIntegralDao.selectListByOpenid(user.getOpenid());
        return detailList;
    }

}